/*
 * BLE模块 - 包含GATT服务和通知功能
 */

#include <stdio.h>
#include <string.h>
#include "esp_err.h"
#include "esp_log.h"
#include "esp_bt.h"
#include "esp_bt_main.h"
#include "esp_bt_defs.h"
#include "esp_bt_device.h"
#include "esp_gap_ble_api.h"
#include "esp_gatts_api.h"
#include "esp_gatt_defs.h"
#include "nvs_flash.h"
#include "esp_sleep.h"
#include "driver/gpio.h"
#include <sys/time.h>
#include <time.h>
#include <stdint.h>
#include <stdlib.h>
#include <errno.h>

// 日志标签
#define BLE_MODULE_TAG "BLE_MODULE"

// 设备名称
#define DEVICE_NAME "Calendar"

// BLE状态变量
static bool ble_initialized = false;

// 自定义服务和特征UUID定义 - 恢复日历专用服务
  #define CUSTOM_SERVICE_UUID          0x1849  // 日历专用服务UUID
  #define CUSTOM_DATA_CHAR_UUID        0x2A4F  // 日历数据特征UUID（仅支持通知，不支持读）
  #define CUSTOM_CONTROL_CHAR_UUID     0x2A50  // 日历控制特征UUID（仅支持writewithoutresponse）
  
  // 兼容旧名称，确保编译通过
  #define CALENDAR_DATA_CHAR_UUID      CUSTOM_DATA_CHAR_UUID
  #define CALENDAR_CONTROL_CHAR_UUID   CUSTOM_CONTROL_CHAR_UUID



// 前向声明
static esp_err_t ble_send_notification(esp_gatt_if_t gatts_if, uint16_t conn_id, uint16_t char_handle, uint8_t *data, uint16_t length);
esp_err_t process_received_frame(const uint8_t *data, uint16_t len);

// GATT服务和特征句柄
static uint16_t service_handle;           // 服务句柄
static uint16_t char_data_handle;         // 数据特征句柄
static uint16_t char_control_handle;      // 控制特征句柄
// 新增：显式记录CCCD句柄
static uint16_t cccd_handle = 0;

// 连接句柄和通知状态
static uint16_t conn_handle = 0;
static bool notify_enabled = false;        // 通知启用状态

// 全局变量，用于存储日历数据和配置
static uint8_t calendar_data[20] = {0};  // 日历数据缓冲区（适配MTU限制）
static uint8_t control_data[4] = {0};    // 控制数据缓冲区
static esp_gatt_if_t current_gatts_if;   // 保存GATT接口
static uint16_t g_att_mtu = 23;           // 当前协商MTU（ATT），默认23

// 采样间隔配置（默认值：10秒）
static uint32_t sample_interval = 10;    // 默认采样间隔为10秒

// 广播参数初始化（提前定义，便于在各事件中使用）
static esp_ble_adv_params_t adv_params = {
    .adv_int_min        = 0x20,
    .adv_int_max        = 0x40,
    .adv_type           = ADV_TYPE_IND,
    .own_addr_type      = BLE_ADDR_TYPE_PUBLIC,
    .peer_addr_type     = BLE_ADDR_TYPE_PUBLIC,
    .peer_addr          = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
    .channel_map        = ADV_CHNL_ALL,
    .adv_filter_policy  = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY,
};



// GATT事件处理函数
static void ble_gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param)
{
    current_gatts_if = gatts_if;  // 保存当前GATT接口
    
    switch (event) {
        case ESP_GATTS_REG_EVT: {
            ESP_LOGI(BLE_MODULE_TAG, "GATT服务注册成功");
            ESP_LOGI(BLE_MODULE_TAG, "GATT接口: %d", gatts_if);
            
            // 创建自定义服务
            esp_bt_uuid_t service_uuid;
            service_uuid.len = ESP_UUID_LEN_16;
            service_uuid.uuid.uuid16 = CUSTOM_SERVICE_UUID;
            
            esp_gatt_srvc_id_t srvc_id = {
                .id = {
                    .uuid = service_uuid,
                    .inst_id = 0
                },
                .is_primary = true
            };
            
            // 使用正确的参数格式创建服务
            esp_err_t ret = esp_ble_gatts_create_service(gatts_if, &srvc_id, 32);
            if (ret != ESP_OK) {
                ESP_LOGE(BLE_MODULE_TAG, "创建服务失败: %d", ret);
            }
            break;
        }
        
        case ESP_GATTS_CREATE_EVT: {
            ESP_LOGI(BLE_MODULE_TAG, "服务创建成功，句柄: %d", param->create.service_handle);
            service_handle = param->create.service_handle;
            
            // 1. 添加通用数据特征（仅支持通知，不支持读）
            esp_gatt_char_prop_t data_prop = ESP_GATT_CHAR_PROP_BIT_NOTIFY;
            esp_bt_uuid_t data_uuid;
            data_uuid.len = ESP_UUID_LEN_16;
            data_uuid.uuid.uuid16 = CUSTOM_DATA_CHAR_UUID;
            
            // 准备特征值属性
            esp_attr_value_t attr_value = {
                .attr_len = sizeof(calendar_data),
                .attr_value = calendar_data
            };
            
            // 添加特征（无读权限，仅支持通知）
            esp_err_t ret = esp_ble_gatts_add_char(service_handle, &data_uuid,
                                               ESP_GATT_PERM_READ,  // 保留读权限以兼容
                                               data_prop,
                                               &attr_value,
                                               NULL);
            if (ret != ESP_OK) {
                ESP_LOGE(BLE_MODULE_TAG, "添加数据特征失败: %d", ret);
            }
            break;
        }
        
        case ESP_GATTS_ADD_CHAR_EVT: {
            ESP_LOGI(BLE_MODULE_TAG, "特征添加成功，句柄: %d", param->add_char.attr_handle);
            
            // 根据当前已添加的特征数量确定下一步操作
            if (char_data_handle == 0) {
                // 这是第一个特征 - 数据特征
                char_data_handle = param->add_char.attr_handle;
                ESP_LOGI(BLE_MODULE_TAG, "通用数据特征添加完成");
                
                // 显式添加CCCD描述符(0x2902)以保证跨平台可靠地启用通知
                esp_bt_uuid_t cccd_uuid;
                cccd_uuid.len = ESP_UUID_LEN_16;
                cccd_uuid.uuid.uuid16 = ESP_GATT_UUID_CHAR_CLIENT_CONFIG; // 0x2902
                uint8_t cccd_init_val[2] = {0x00, 0x00};
                esp_attr_value_t cccd_attr = {
                    .attr_len = sizeof(cccd_init_val),
                    .attr_value = cccd_init_val,
                };
                esp_err_t dret = esp_ble_gatts_add_char_descr(
                    service_handle,
                    &cccd_uuid,
                    ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE,
                    &cccd_attr,
                    NULL
                );
                if (dret != ESP_OK) {
                    ESP_LOGE(BLE_MODULE_TAG, "添加CCCD描述符失败: %d", dret);
                } else {
                    ESP_LOGI(BLE_MODULE_TAG, "CCCD描述符添加请求已发送，等待ESP_GATTS_ADD_CHAR_DESCR_EVT事件");
                }
                
                // 2. 添加通用控制特征（仅支持writewithoutresponse）
            esp_gatt_char_prop_t control_prop = ESP_GATT_CHAR_PROP_BIT_WRITE_NR;  // 仅支持writewithoutresponse
                esp_bt_uuid_t control_uuid;
                control_uuid.len = ESP_UUID_LEN_16;
                control_uuid.uuid.uuid16 = CUSTOM_CONTROL_CHAR_UUID;
              
              // 准备特征值属性
              esp_attr_value_t control_attr_value = {
                  .attr_len = sizeof(control_data),
                  .attr_value = control_data
              };
              
              // 添加控制特征（仅支持writewithoutresponse）
              esp_err_t ret = esp_ble_gatts_add_char(service_handle, &control_uuid,
                                 ESP_GATT_PERM_WRITE,
                                 control_prop,
                                 &control_attr_value,
                                 NULL);
              if (ret != ESP_OK) {
                  ESP_LOGE(BLE_MODULE_TAG, "添加控制特征失败: %d", ret);
              }
            } else {
                // 这是第二个特征 - 控制特征
                char_control_handle = param->add_char.attr_handle;
                ESP_LOGI(BLE_MODULE_TAG, "通用控制特征添加完成");
                
                // 启动服务（只有两个特征：数据特征和控制特征）
                esp_ble_gatts_start_service(service_handle);
                ESP_LOGI(BLE_MODULE_TAG, "自定义通用服务启动成功，包含两个特征：通用数据（仅通知）和通用控制（writewithoutresponse）");
            }
            break;
        }
        
        // 新增：描述符添加事件，用于记录CCCD句柄
        case ESP_GATTS_ADD_CHAR_DESCR_EVT: {
            ESP_LOGI(BLE_MODULE_TAG, "描述符添加成功，句柄: %d", param->add_char_descr.attr_handle);
            // 记录CCCD句柄
            cccd_handle = param->add_char_descr.attr_handle;
            ESP_LOGI(BLE_MODULE_TAG, "CCCD描述符句柄已记录: %d", cccd_handle);
            ESP_LOGI(BLE_MODULE_TAG, "CCCD描述符已准备就绪，可以接收客户端通知订阅请求");
            break;
        }
        
        case ESP_GATTS_READ_EVT: {
            ESP_LOGI(BLE_MODULE_TAG, "收到读取请求，句柄: %d", param->read.handle);
            
            // 准备响应数据
            esp_gatt_rsp_t rsp = {
                .attr_value = {
                    .handle = param->read.handle,
                    .len = 0,
                    .value = {0}
                }
            };
            
            if (param->read.handle == char_data_handle) {
                // 读取日历数据（数据特征已改为不支持读操作，这里保留兼容性处理）
                rsp.attr_value.len = sizeof(calendar_data);
                memcpy(rsp.attr_value.value, calendar_data, sizeof(calendar_data));
                ESP_LOGI(BLE_MODULE_TAG, "返回日历数据（兼容性处理）");
            }
            
            esp_ble_gatts_send_response(gatts_if, param->read.conn_id, param->read.trans_id,
                                      ESP_GATT_OK, &rsp);
            break;
        }
        
        case ESP_GATTS_MTU_EVT: {
            g_att_mtu = param->mtu.mtu;
            ESP_LOGI(BLE_MODULE_TAG, "MTU更新事件: mtu=%d, notify最大负载=%d", param->mtu.mtu, (int)(g_att_mtu - 3));
            break;
        }
        case ESP_GATTS_WRITE_EVT: {
            // 增强写入日志，便于定位订阅断开问题
            ESP_LOGI(BLE_MODULE_TAG, "WRITE_EVT: handle=%d, len=%d, is_prep=%d, need_rsp=%d, offset=%d", 
                     param->write.handle, param->write.len, param->write.is_prep, param->write.need_rsp, param->write.offset);
            
            // 打印接收到的完整数据内容（十六进制格式）
            if (param->write.len > 0) {
                ESP_LOGI(BLE_MODULE_TAG, "接收数据内容（十六进制）:");
                char hex_buffer[512]; // 缓冲区用于存储十六进制字符串
                char *ptr = hex_buffer;
                int remaining = sizeof(hex_buffer);
                
                // 将每个字节转换为十六进制格式
                for (int i = 0; i < param->write.len && remaining > 3; i++) {
                    int written = snprintf(ptr, remaining, "%02X ", param->write.value[i]);
                    if (written > 0 && written < remaining) {
                        ptr += written;
                        remaining -= written;
                    }
                }
                ESP_LOGI(BLE_MODULE_TAG, "%s", hex_buffer);
                
                // 同时打印ASCII可显示字符（便于调试文本数据）
                ESP_LOGI(BLE_MODULE_TAG, "接收数据内容（ASCII）:");
                ptr = hex_buffer;
                remaining = sizeof(hex_buffer);
                
                for (int i = 0; i < param->write.len && remaining > 2; i++) {
                    uint8_t ch = param->write.value[i];
                    if (ch >= 32 && ch <= 126) { // 可打印ASCII字符
                        int written = snprintf(ptr, remaining, "%c ", ch);
                        if (written > 0 && written < remaining) {
                            ptr += written;
                            remaining -= written;
                        }
                    } else {
                        int written = snprintf(ptr, remaining, ". "); // 不可打印字符用点表示
                        if (written > 0 && written < remaining) {
                            ptr += written;
                            remaining -= written;
                        }
                    }
                }
                ESP_LOGI(BLE_MODULE_TAG, "%s", hex_buffer);
            }
            
            if (!param->write.is_prep) {  // 非准备写
                ESP_LOGI(BLE_MODULE_TAG, "收到写入请求，句柄: %d, 长度: %d", param->write.handle, param->write.len);
                // 检查是否是CCCD通知配置（使用记录的 cccd_handle）
                if (cccd_handle != 0 && param->write.handle == cccd_handle) {
                    ESP_LOGI(BLE_MODULE_TAG, "CCCD写入事件 - 通知订阅请求");
                    if (param->write.len >= 2) {
                        uint16_t cccd_val = (uint16_t)(param->write.value[0] | (param->write.value[1] << 8));
                        ESP_LOGI(BLE_MODULE_TAG, "CCCD值: 0x%04x (handle=%d)", cccd_val, param->write.handle);
                        if (cccd_val == 0x0001) {  // 客户端开启通知(0x0001)
                            ESP_LOGI(BLE_MODULE_TAG, "通知已启用 - 订阅成功");
                            notify_enabled = true;
                            conn_handle = param->write.conn_id;  // 记录连接ID
                        } else if (cccd_val == 0x0000) {
                            ESP_LOGI(BLE_MODULE_TAG, "通知已禁用 - 取消订阅");
                            notify_enabled = false;
                        } else {
                            ESP_LOGW(BLE_MODULE_TAG, "未知的CCCD值: 0x%04X", cccd_val);
                        }
                        // 对需要响应的写入进行ACK，防止客户端等待超时导致断开
                        if (param->write.need_rsp) {
                            esp_gatt_status_t st = ESP_GATT_OK;
                            esp_err_t r = esp_ble_gatts_send_response(gatts_if, param->write.conn_id, param->write.trans_id, st, NULL);
                            if (r != ESP_OK) {
                                ESP_LOGE(BLE_MODULE_TAG, "CCCD写入响应失败: %s", esp_err_to_name(r));
                            } else {
                                ESP_LOGI(BLE_MODULE_TAG, "已发送CCCD写入响应");
                            }
                        }
                        // 如通知开启，发送当前日历数据作为初始通知（确保已ACK）
                        if (notify_enabled && char_data_handle != 0 && current_gatts_if != 0) {
                            ESP_LOGI(BLE_MODULE_TAG, "订阅成功");
                        }
                    } else {
                        ESP_LOGW(BLE_MODULE_TAG, "CCCD写入长度不足: %d", param->write.len);
                        if (param->write.need_rsp) {
                            esp_ble_gatts_send_response(gatts_if, param->write.conn_id, param->write.trans_id, ESP_GATT_INVALID_ATTR_LEN, NULL);
                        }
                    }
                    break;  // 处理完成，跳出switch-case，避免重复处理
                }
                // 常规特征写入处理
                if (param->write.handle == char_control_handle) {
                    // 优先处理协议命令帧（FRAME_HEADER_CMD=0xAA）
                    if (param->write.len >= 9 && param->write.value[0] == 0xAA) {
                        esp_err_t pret = process_received_frame(param->write.value, param->write.len);
                        if (pret != ESP_OK) {
                            ESP_LOGE(BLE_MODULE_TAG, "处理命令帧失败: %s", esp_err_to_name(pret));
                        }
                        if (param->write.need_rsp) {
                            esp_ble_gatts_send_response(gatts_if, param->write.conn_id, param->write.trans_id, ESP_GATT_OK, NULL);
                        }
                        // 命令帧已处理，直接返回
                        return;
                    }
                    // 保存控制数据（兼容旧实现）
                    if (param->write.len <= sizeof(control_data)) {
                        memcpy(control_data, param->write.value, param->write.len);
                        ESP_LOGI(BLE_MODULE_TAG, "控制数据更新成功");
                    } else {
                        ESP_LOGW(BLE_MODULE_TAG, "控制数据长度超限: %d", param->write.len);
                    }
                    if (param->write.need_rsp) {
                        esp_ble_gatts_send_response(gatts_if, param->write.conn_id, param->write.trans_id, ESP_GATT_OK, NULL);
                    }
 } else {
                    ESP_LOGW(BLE_MODULE_TAG, "未知的写入句柄: %d", param->write.handle);
                    if (param->write.need_rsp) {
                        esp_ble_gatts_send_response(gatts_if, param->write.conn_id, param->write.trans_id, ESP_GATT_OK, NULL);
                    }
                }
            } else {
                // 准备写：记录日志并按需响应
                ESP_LOGI(BLE_MODULE_TAG, "收到Prepare Write: handle=%d, len=%d, offset=%d", param->write.handle, param->write.len, param->write.offset);
                if (param->write.need_rsp) {
                    esp_ble_gatts_send_response(gatts_if, param->write.conn_id, param->write.trans_id, ESP_GATT_OK, NULL);
                }
            }
            break;
        }
        
        // 移除不支持的ESP_GATTS_CCCD_EVT事件
        // ...
        
        case ESP_GATTS_CONNECT_EVT: {
            ESP_LOGI(BLE_MODULE_TAG, "设备连接成功，Conn ID: %d", param->connect.conn_id);
            conn_handle = param->connect.conn_id;
            notify_enabled = false;  // 重置通知状态
            ESP_LOGI(BLE_MODULE_TAG, "已建立BLE连接，准备数据交互");
            break;
        }
        
        case ESP_GATTS_DISCONNECT_EVT: {
            ESP_LOGI(BLE_MODULE_TAG, "设备断开连接，Conn ID: %d", param->disconnect.conn_id);
            conn_handle = 0;
            notify_enabled = false;
            ESP_LOGI(BLE_MODULE_TAG, "断开连接，等待新的连接请求");
            // 在断开事件中重启广播，确保其他APP可以再次发现设备
            esp_err_t adv_ret = esp_ble_gap_start_advertising(&adv_params);
            if (adv_ret == ESP_OK) {
                ESP_LOGI(BLE_MODULE_TAG, "断开后重启广播成功");
            } else {
                ESP_LOGE(BLE_MODULE_TAG, "断开后重启广播失败: %s", esp_err_to_name(adv_ret));
            }
            break;
        }
        
        default:
            ESP_LOGI(BLE_MODULE_TAG, "GATT事件: %d", event);
            break;
    }
}



// 定义制造商数据 - 添加0xffff信息
    static uint8_t manufacturer_data[] = {
        0x01, 0x02,  // 制造商ID (示例)
        0xff, 0xff   // 0xffff相关信息
    };

    // 广播数据配置 - 适配ESP-IDF v5.5.1
    static esp_ble_adv_data_t adv_data = {
        .include_name = true,
        .include_txpower = true,
        .flag = ESP_BLE_ADV_FLAG_GEN_DISC | ESP_BLE_ADV_FLAG_BREDR_NOT_SPT,
        // 添加manufacturer data字段（ESP-IDF v5.5.1使用p_manufacturer_data）
        .p_manufacturer_data = manufacturer_data,
        .manufacturer_len = sizeof(manufacturer_data),
    };

/**
 * @brief BLE GAP事件处理函数
 */
static void ble_gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param)
{
    switch (event) {
        case ESP_GAP_BLE_ADV_DATA_SET_COMPLETE_EVT:
            ESP_LOGI(BLE_MODULE_TAG, "广播数据设置完成");
            // 开始广播
            esp_ble_gap_start_advertising(&adv_params);
            break;
        case ESP_GAP_BLE_ADV_START_COMPLETE_EVT:
            if (param->adv_start_cmpl.status == ESP_BT_STATUS_SUCCESS) {
                ESP_LOGI(BLE_MODULE_TAG, "开始广播成功");
            } else {
                ESP_LOGE(BLE_MODULE_TAG, "开始广播失败: %d", param->adv_start_cmpl.status);
            }
            break;
        case ESP_GAP_BLE_SCAN_RSP_DATA_SET_COMPLETE_EVT:
            ESP_LOGI(BLE_MODULE_TAG, "扫描响应数据设置完成");
            break;
        case ESP_GAP_BLE_UPDATE_CONN_PARAMS_EVT:
            ESP_LOGI(BLE_MODULE_TAG, "更新连接参数: min_int=%d, max_int=%d, latency=%d, timeout=%d, status=%d", 
                     param->update_conn_params.min_int, param->update_conn_params.max_int, param->update_conn_params.latency, 
                     param->update_conn_params.timeout, param->update_conn_params.status);
            break;
        // 移除不存在的ESP_GAP_BLE_CONNECT_EVT事件
        // case ESP_GAP_BLE_CONNECT_EVT:
        //     ESP_LOGI(BLE_MODULE_TAG, "设备连接，停止广播以节省电量");
        //     esp_ble_gap_stop_advertising();
        //     break;
        
        default:
            ESP_LOGI(BLE_MODULE_TAG, "GAP事件: %d", event);
            break;
    }
}

// 配置低功耗设置
static void configure_low_power() {
    // 1. 注释掉未定义的宏，使用更安全的方式
    // 注意：ESP-IDF v5.5.1中可能需要不同的方式来控制外设时钟
    // periph_module_disable(PERIPH_UART0_MODULE);  // 这些宏在当前ESP-IDF版本中未定义
    // periph_module_disable(PERIPH_SPI_MODULE);
    
    // 2. 配置深度睡眠唤醒源（可根据需要启用）
    esp_sleep_enable_timer_wakeup(sample_interval * 1000);  // 单位：us（使用默认采样间隔10秒）
    
    // 3. 释放GPIO引脚（避免漏电）
    gpio_deep_sleep_hold_dis();
}

// 底层BLE数据发送函数（内部使用）
static esp_err_t ble_send_notification(esp_gatt_if_t gatts_if, uint16_t conn_id, uint16_t char_handle, uint8_t *data, uint16_t length)
{
    // 检查参数 (注意：conn_id=0 是有效的连接ID，不应该被拒绝)
    if (gatts_if == 0 || char_handle == 0 || data == NULL || length == 0) {
        ESP_LOGE(BLE_MODULE_TAG, "无效参数: gatts_if=%d, conn_id=%d, char_handle=%d, data=%p, length=%d", 
                gatts_if, conn_id, char_handle, data, length);
        return ESP_ERR_INVALID_ARG;
    }
    
    // 检查是否超过当前协商MTU的最大负载（ATT MTU-3字节开销）
    uint16_t max_payload = (g_att_mtu > 3) ? (g_att_mtu - 3) : 0;
    if (max_payload == 0 || length > max_payload) {
        ESP_LOGW(BLE_MODULE_TAG, "通知长度超限，自动截断: length=%d, 当前MTU=%d, 最大负载=%d", length, g_att_mtu, max_payload);
        length = max_payload; // 自动截断到最大允许长度
    }
    
    ESP_LOGI(BLE_MODULE_TAG, "通过notify机制发送通知，长度: %d", length);
    // 使用 esp_ble_gatts_send_indicate 的 need_confirm=false 来发送 notify
    esp_err_t ret = esp_ble_gatts_send_indicate(gatts_if, conn_id, char_handle, length, data, false);
    if (ret != ESP_OK) {
        ESP_LOGE(BLE_MODULE_TAG, "发送通知失败: %s", esp_err_to_name(ret));
    }
    return ret;
}

// 发送数据函数 - 通用数据发送
esp_err_t ble_send_data(uint8_t *data, uint16_t data_len)
{
    if (conn_handle == 0 || current_gatts_if == 0) {
        ESP_LOGW(BLE_MODULE_TAG, "无法发送数据: BLE未初始化或没有连接");
        return ESP_ERR_INVALID_STATE;
    }
    
    ESP_LOGI(BLE_MODULE_TAG, "发送通用数据，数据长度: %d", data_len);
    
    // 直接发送数据通知
    return ble_send_notification(current_gatts_if, conn_handle, char_data_handle, data, data_len);
}

// 更新并发送日历数据
esp_err_t ble_update_calendar_data(uint8_t *data, uint16_t length)
{
    // 确保数据长度不超过缓冲区大小
    if (length > sizeof(calendar_data)) {
        ESP_LOGE(BLE_MODULE_TAG, "日历数据过长，最大支持 %d 字节", sizeof(calendar_data));
        return ESP_ERR_INVALID_SIZE;
    }
    
    // 更新日历数据缓冲区
    memcpy(calendar_data, data, length);
    ESP_LOGI(BLE_MODULE_TAG, "日历数据已更新，长度: %d", length);
    
    // 如果有连接且通知已启用，发送通知
    if (conn_handle != 0 && char_data_handle != 0 && current_gatts_if != 0 && notify_enabled) {
        ESP_LOGI(BLE_MODULE_TAG, "发送日历数据通知");
        return ble_send_notification(current_gatts_if, conn_handle, char_data_handle, data, length);
    }
    
    ESP_LOGI(BLE_MODULE_TAG, "当前没有活跃连接或通知未启用，数据已缓存但未发送通知");
    return ESP_OK;
}

// 获取当前控制数据
esp_err_t ble_get_control_data(uint8_t *data, uint16_t *length)
{
    if (data == NULL || length == NULL) {
        return ESP_ERR_INVALID_ARG;
    }
    
    memcpy(data, control_data, sizeof(control_data));
    *length = sizeof(control_data);
    return ESP_OK;
}

// 获取当前采样间隔配置
esp_err_t ble_get_sample_interval(uint32_t *interval)
{
    if (interval == NULL) {
        return ESP_ERR_INVALID_ARG;
    }
    
    *interval = sample_interval;
    return ESP_OK;
}

// 设置采样间隔配置
esp_err_t ble_set_sample_interval(uint32_t interval)
{
    // 参数检查
    if (interval < 1 || interval > 3600) {
        ESP_LOGE(BLE_MODULE_TAG, "采样间隔超出范围 (1-3600秒): %u", interval);
        return ESP_ERR_INVALID_ARG;
    }
    
    // 更新采样间隔
    sample_interval = interval;
    ESP_LOGI(BLE_MODULE_TAG, "采样间隔已更新为: %u秒", interval);
    
    return ESP_OK;
}

/**
 * @brief 按需发送通用数据（默认0xffff），不再定时下发
 * @note 仅在已连接且客户端已启用通知（CCCD=0x0001）时发送；该函数本身不进行任何定时或重试
 * @return esp_err_t 操作结果
 */
esp_err_t ble_send_generic_data(void)
{
    ESP_LOGI(BLE_MODULE_TAG, "准备发送通用数据 (0xffff)");
    
    if (conn_handle == 0 || current_gatts_if == 0 || char_data_handle == 0) {
        ESP_LOGW(BLE_MODULE_TAG, "无法发送数据: BLE未初始化或没有连接");
        return ESP_ERR_INVALID_STATE;
    }
    
    // 检查通知是否启用
    if (!notify_enabled) {
        ESP_LOGW(BLE_MODULE_TAG, "通知功能未启用，无法发送数据");
        return ESP_ERR_INVALID_STATE;
    }
    
    // 准备通用数据 - 默认发送0xffff
    uint8_t data[3] = {
        0x01,  // 数据类型标识
        0xff,  // 0xffff的高字节
        0xff   // 0xffff的低字节
    };
    
    // 直接发送通知
    esp_err_t ret = ble_send_notification(current_gatts_if, conn_handle, char_data_handle, data, sizeof(data));
    if (ret == ESP_OK) {
        ESP_LOGI(BLE_MODULE_TAG, "通用数据发送成功 (0xffff)");
    } else {
        ESP_LOGE(BLE_MODULE_TAG, "通用数据发送失败: %d", ret);
    }
    
    return ret;
}

/**
 * @brief 初始化BLE模块
 * @return esp_err_t 初始化结果
 */
esp_err_t ble_init(void)
{
    ESP_LOGI(BLE_MODULE_TAG, "初始化BLE模块 (ESP32-D0WD-V3 + ESP-IDF v5.5.1)");
    
    // 检查是否已经初始化
    if (ble_initialized) {
        ESP_LOGW(BLE_MODULE_TAG, "BLE模块已经初始化");
        return ESP_OK;
    }
    
    // 重置状态变量
    conn_handle = 0;
    char_data_handle = 0;
    char_control_handle = 0;
    current_gatts_if = 0;
    notify_enabled = false;
    
    // 清零数据缓冲区
    memset(calendar_data, 0, sizeof(calendar_data));
    memset(control_data, 0, sizeof(control_data));

    // 初始化NVS - 使用ESP-IDF v5.5.1推荐的方式
    esp_err_t ret = nvs_flash_init();
    if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
        ESP_LOGW(BLE_MODULE_TAG, "NVS分区需要擦除，执行擦除操作...");
        if (nvs_flash_erase() != ESP_OK) {
            ESP_LOGE(BLE_MODULE_TAG, "NVS分区擦除失败");
            return ESP_FAIL;
        }
        ret = nvs_flash_init();
    }
    
    if (ret != ESP_OK) {
        ESP_LOGE(BLE_MODULE_TAG, "NVS初始化失败: %s", esp_err_to_name(ret));
        return ret;
    }
    ESP_LOGI(BLE_MODULE_TAG, "NVS初始化成功");
    
    // 采样间隔功能已移除，不再从NVS加载配置

    // 初始化蓝牙控制器配置
    esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT();
    ret = esp_bt_controller_init(&bt_cfg);
    if (ret != ESP_OK) {
        ESP_LOGE(BLE_MODULE_TAG, "初始化蓝牙控制器失败: %s", esp_err_to_name(ret));
        return ret;
    }
    
    // 启用蓝牙控制器
    ret = esp_bt_controller_enable(ESP_BT_MODE_BLE);
    if (ret != ESP_OK) {
        ESP_LOGE(BLE_MODULE_TAG, "启用蓝牙控制器失败: %s", esp_err_to_name(ret));
        return ret;
    }
    
    // 初始化BLE协议栈
    ret = esp_bluedroid_init();
    if (ret != ESP_OK) {
        ESP_LOGE(BLE_MODULE_TAG, "初始化BLE协议栈失败: %s", esp_err_to_name(ret));
        return ret;
    }
    
    // 启用BLE协议栈
    ret = esp_bluedroid_enable();
    if (ret != ESP_OK) {
        ESP_LOGE(BLE_MODULE_TAG, "启用BLE协议栈失败: %s", esp_err_to_name(ret));
        return ret;
    }
    
    // 注册BLE GAP回调函数
    ret = esp_ble_gap_register_callback(ble_gap_event_handler);
    if (ret != ESP_OK) {
        ESP_LOGE(BLE_MODULE_TAG, "注册BLE GAP回调函数失败: %s", esp_err_to_name(ret));
        return ret;
    }
    
    // 注册BLE GATT回调函数
    ret = esp_ble_gatts_register_callback(ble_gatts_event_handler);
    if (ret != ESP_OK) {
        ESP_LOGE(BLE_MODULE_TAG, "注册BLE GATT回调函数失败: %s", esp_err_to_name(ret));
        return ret;
    }
    
    // 应用程序注册GATT服务
    ret = esp_ble_gatts_app_register(0);
    if (ret != ESP_OK) {
        ESP_LOGE(BLE_MODULE_TAG, "应用程序注册GATT服务失败: %s", esp_err_to_name(ret));
        return ret;
    }
    
    ESP_LOGI(BLE_MODULE_TAG, "GATT服务注册已启动，将在回调中创建自定义日历服务");

    // 设置设备名称
    ret = esp_ble_gap_set_device_name(DEVICE_NAME);
    if (ret != ESP_OK) {
        ESP_LOGE(BLE_MODULE_TAG, "设置设备名称失败: %s", esp_err_to_name(ret));
        return ret;
    }

    // 设置广播数据
    ret = esp_ble_gap_config_adv_data(&adv_data);
    if (ret != ESP_OK) {
        ESP_LOGE(BLE_MODULE_TAG, "设置广播数据失败: %s", esp_err_to_name(ret));
        return ret;
    }
    
    ESP_LOGI(BLE_MODULE_TAG, "广播配置完成，包含通用服务UUID: 0x%04x", CUSTOM_SERVICE_UUID);
    ESP_LOGI(BLE_MODULE_TAG, "制造商数据已添加，包含0xffff信息");

    // 打印蓝牙MAC地址
    const uint8_t *mac = esp_bt_dev_get_address();
    ESP_LOGI(BLE_MODULE_TAG, "蓝牙MAC地址: %02x:%02x:%02x:%02x:%02x:%02x", 
             mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
    
    // 配置低功耗设置
    configure_low_power();
    
    ESP_LOGI(BLE_MODULE_TAG, "BLE模块初始化完成，当前采样间隔: %us", sample_interval);
    ble_initialized = true;
    return ESP_OK;
}


// 协议常量与结构
// 帧头/尾与类型定义（遵循 BLE_PROTOCOL_DESIGN.md）
#define FRAME_HEADER_CMD  0xAA
#define FRAME_HEADER_RESP 0xBB
#define FRAME_TAIL_CMD    0x55
#define FRAME_TAIL_RESP   0x66

#define CMD_TYPE_DATA       0x01
#define CMD_TYPE_FILE       0x02
#define CMD_TYPE_CONTROL    0x03
#define CMD_TYPE_TIME_SYNC  0x04

#define RESP_TYPE_ACK         0x01
#define RESP_TYPE_RETRANSMIT  0x02
#define RESP_TYPE_COMPLETE    0x03
#define RESP_TYPE_ERROR       0x04

#define MAX_DATA_PER_PACKET 244
#define MAX_PACKETS 65535

// 错误码
#define ERR_SUCCESS        0
#define ERR_CRC_MISMATCH   1
#define ERR_FRAME_FORMAT   2
#define ERR_BUFFER_FULL    3
#define ERR_TIMEOUT        4
#define ERR_PACKET_LOST    5

// 时间同步相关NVS键
#define NVS_TZ_OFFSET_KEY   "tz_offset_min"

// 命令帧结构（用于内部解析/构造）
typedef struct {
    uint8_t header;
    uint8_t type;
    uint16_t total_packets;   // LE
    uint16_t packet_index;    // LE
    uint16_t data_len;        // LE
    uint8_t  data[MAX_DATA_PER_PACKET];
    uint16_t checksum;        // LE (XMODEM)
    uint8_t tail;
} cmd_frame_t;

// 响应帧结构（通知特征发送）
typedef struct {
    uint8_t header;
    uint8_t type;
    uint16_t packet_index; // LE
    uint16_t info;         // LE
    uint16_t checksum;     // LE
    uint8_t tail;
} resp_frame_t;

// 大数据重组缓冲管理
typedef struct {
    uint8_t *buffer;           // 按包序号存放，每包 MAX_DATA_PER_PACKET
    size_t   buffer_size;      // 分配的缓冲区大小
    size_t   total_size;       // 实际数据总长度（累计 data_len）
    uint16_t total_packets;    // 期望包数
    uint8_t *received_mask;    // 每包1字节标记是否收到
    bool     is_active;        // 是否正在进行重组
    bool     is_complete;      // 是否重组完成
    uint16_t received_count;   // 已收到的包计数
} data_assembly_t;

static data_assembly_t g_assembly = {0};

// 时间同步回调（供应用层注册，用于交互）
static void (*time_sync_cb)(uint64_t utc_ms, int16_t tz_offset_min, uint8_t flags) = NULL;

// -------------------------- 辅助函数声明 --------------------------
static inline uint16_t le16(const uint8_t *p) {
    return (uint16_t)p[0] | ((uint16_t)p[1] << 8);
}
static inline uint64_t le64(const uint8_t *p) {
    return ((uint64_t)p[0]) |
           ((uint64_t)p[1] << 8) |
           ((uint64_t)p[2] << 16) |
           ((uint64_t)p[3] << 24) |
           ((uint64_t)p[4] << 32) |
           ((uint64_t)p[5] << 40) |
           ((uint64_t)p[6] << 48) |
           ((uint64_t)p[7] << 56);
}

static uint16_t calculate_crc16(const uint8_t *data, size_t len);
esp_err_t process_received_frame(const uint8_t *data, uint16_t len);
static esp_err_t send_response_frame(uint8_t type, uint16_t packet_index, uint16_t info);
static esp_err_t apply_time_sync_payload(const uint8_t *payload, uint16_t len);
static void assembly_reset(data_assembly_t *asmblr);
static esp_err_t assembly_begin(data_assembly_t *asmblr, uint16_t total_packets);
static esp_err_t assembly_store(data_assembly_t *asmblr, uint16_t packet_index, const uint8_t *chunk, uint16_t chunk_len);

// ------------------ 协议实现：CRC16(XMODEM) ------------------
static uint16_t calculate_crc16(const uint8_t *data, size_t len) {
    uint16_t crc = 0x0000; // XMODEM初值
    const uint16_t poly = 0x1021;
    for (size_t i = 0; i < len; ++i) {
        crc ^= ((uint16_t)data[i]) << 8;
        for (int j = 0; j < 8; ++j) {
            if (crc & 0x8000) {
                crc = (crc << 1) ^ poly;
            } else {
                crc <<= 1;
            }
        }
    }
    return crc;
}

// ------------------ 协议实现：大数据重组 ------------------
static void assembly_reset(data_assembly_t *asmblr) {
    if (!asmblr) return;
    if (asmblr->buffer) { free(asmblr->buffer); asmblr->buffer = NULL; }
    if (asmblr->received_mask) { free(asmblr->received_mask); asmblr->received_mask = NULL; }
    asmblr->total_packets = 0;
    asmblr->received_count = 0;
    asmblr->total_size = 0;
    asmblr->is_active = false;
    asmblr->is_complete = false;
}

static esp_err_t assembly_begin(data_assembly_t *asmblr, uint16_t total_packets) {
    if (!asmblr || total_packets == 0) {
        return ESP_ERR_INVALID_ARG;
    }
    assembly_reset(asmblr);
    size_t buffer_size = (size_t)total_packets * MAX_DATA_PER_PACKET;
    // 防止过大分配
    if (buffer_size > (size_t)MAX_PACKETS * MAX_DATA_PER_PACKET) {
        return ESP_ERR_NO_MEM;
    }
    asmblr->buffer = (uint8_t *)calloc(1, buffer_size);
    asmblr->received_mask = (uint8_t *)calloc(1, total_packets);
    if (!asmblr->buffer || !asmblr->received_mask) {
        assembly_reset(asmblr);
        return ESP_ERR_NO_MEM;
    }
    asmblr->total_packets = total_packets;
    asmblr->is_active = true;
    asmblr->is_complete = false;
    asmblr->total_size = 0;
    asmblr->received_count = 0;
    return ESP_OK;
}

static esp_err_t assembly_store(data_assembly_t *asmblr, uint16_t packet_index, const uint8_t *chunk, uint16_t chunk_len) {
    if (!asmblr || !asmblr->is_active || !chunk) return ESP_ERR_INVALID_STATE;
    if (packet_index >= asmblr->total_packets || chunk_len > MAX_DATA_PER_PACKET) return ESP_ERR_INVALID_ARG;
    size_t offset = (size_t)packet_index * MAX_DATA_PER_PACKET;
    memcpy(asmblr->buffer + offset, chunk, chunk_len);
    if (!asmblr->received_mask[packet_index]) {
        asmblr->received_mask[packet_index] = 1;
        asmblr->received_count++;
    }
    // 估算总大小（最后一包长度可能小于MAX_DATA_PER_PACKET）
    if (packet_index == asmblr->total_packets - 1) {
        asmblr->total_size = offset + chunk_len;
    }
    // 判断是否全部收到
    if (asmblr->received_count >= asmblr->total_packets) {
        asmblr->is_complete = true;
        asmblr->is_active = false;
    }
    return ESP_OK;
}

// ------------------ 协议实现：发送响应帧 ------------------
static esp_err_t send_response_frame(uint8_t resp_type, uint16_t packet_index, uint16_t info) {
    uint8_t raw[1 + 1 + 2 + 2 + 2 + 1]; // hdr + type + pkt_idx + info + crc + tail = 9字节
    size_t pos = 0;
    raw[pos++] = FRAME_HEADER_RESP; // 0xAB
    raw[pos++] = resp_type;        // 0x81/0x82/0x83
    raw[pos++] = (uint8_t)(packet_index & 0xFF);
    raw[pos++] = (uint8_t)((packet_index >> 8) & 0xFF);
    raw[pos++] = (uint8_t)(info & 0xFF);
    raw[pos++] = (uint8_t)((info >> 8) & 0xFF);
    uint16_t crc = calculate_crc16(&raw[1], 1 + 2 + 2); // 对 type + pkt_idx + info 计算CRC
    raw[pos++] = (uint8_t)(crc & 0xFF);
    raw[pos++] = (uint8_t)((crc >> 8) & 0xFF);
    raw[pos++] = FRAME_TAIL_RESP;       // 0x55
    return ble_send_notification(current_gatts_if, conn_handle, char_data_handle, raw, (uint16_t)pos);
}

// ------------------ 协议实现：应用时间同步Payload ------------------
static esp_err_t apply_time_sync_payload(const uint8_t *payload, uint16_t len) {
    if (!payload || len < 13) return ESP_ERR_INVALID_ARG;
    uint8_t subcmd = payload[0];
    if (subcmd != 0x01) return ESP_ERR_INVALID_ARG; // 目前仅支持子命令0x01
    // 小端解析
    uint64_t utc_ms = ((uint64_t)payload[1]) | ((uint64_t)payload[2] << 8) | ((uint64_t)payload[3] << 16) |
                      ((uint64_t)payload[4] << 24) | ((uint64_t)payload[5] << 32) | ((uint64_t)payload[6] << 40) |
                      ((uint64_t)payload[7] << 48) | ((uint64_t)payload[8] << 56);
    int16_t tz_offset_min = (int16_t)((uint16_t)payload[9] | ((uint16_t)payload[10] << 8));
    uint8_t flags = payload[12];

    // 当前系统时间
    struct timeval tv;
    gettimeofday(&tv, NULL);
    int64_t now_ms = (int64_t)tv.tv_sec * 1000 + tv.tv_usec / 1000;
    int64_t diff_ms = (int64_t)utc_ms - now_ms;

    bool smooth = (flags & 0x01) != 0;
    ESP_LOGI(BLE_MODULE_TAG, "Time sync: diff=%lld ms, smooth=%d, tz_offset_min=%d", (long long)diff_ms, (int)smooth, (int)tz_offset_min);
    // 简化：若平滑且偏差较小（<=2s），直接设置；否则马上设置
    tv.tv_sec = (time_t)(utc_ms / 1000);
    tv.tv_usec = (suseconds_t)((utc_ms % 1000) * 1000);
    int st = settimeofday(&tv, NULL);
    if (st != 0) {
        ESP_LOGE(BLE_MODULE_TAG, "settimeofday失败, errno=%d", errno);
        return ESP_FAIL;
    }

    // 将时区偏移写入NVS（以分钟存储，使用int32）
    nvs_handle_t h;
    esp_err_t err = nvs_open("ble_mod", NVS_READWRITE, &h);
    if (err == ESP_OK) {
        err = nvs_set_i32(h, NVS_TZ_OFFSET_KEY, (int32_t)tz_offset_min);
        if (err == ESP_OK) err = nvs_commit(h);
        nvs_close(h);
    }
    if (err != ESP_OK) {
        ESP_LOGW(BLE_MODULE_TAG, "保存时区偏移失败: %s", esp_err_to_name(err));
    }

    // 回调通知其他模块（如calendar.c）
    if (time_sync_cb) {
        time_sync_cb(utc_ms, tz_offset_min, flags);
    }
    return ESP_OK;
}

// ------------------ 协议实现：处理收到的命令帧或数据帧 ------------------
esp_err_t process_received_frame(const uint8_t *raw, uint16_t len) {
    if (!raw || len < 9) return ESP_ERR_INVALID_ARG;
    uint8_t header = raw[0];
    uint8_t tail = raw[len - 1];
    if (tail != FRAME_TAIL_CMD) return ESP_ERR_INVALID_ARG;

    if (header == FRAME_HEADER_CMD) {
        // 解析命令帧
        if (len < 11) return ESP_ERR_INVALID_ARG; // 最小长度检查
        uint8_t cmd_type = raw[1];
        uint16_t total_packets = (uint16_t)(raw[2] | (raw[3] << 8));
        uint16_t packet_index  = (uint16_t)(raw[4] | (raw[5] << 8));
        uint16_t data_len      = (uint16_t)(raw[6] | (raw[7] << 8));
        if (data_len > MAX_DATA_PER_PACKET) {
            send_response_frame(RESP_TYPE_ERROR, packet_index, ERR_FRAME_FORMAT);
            return ESP_ERR_INVALID_SIZE;
        }
        size_t expected = 1 + 1 + 2 + 2 + 2 + data_len + 2 + 1; // hdr+type+total+idx+len+data+crc+tail
        if (len != expected) {
            send_response_frame(RESP_TYPE_ERROR, packet_index, ERR_FRAME_FORMAT);
            return ESP_ERR_INVALID_SIZE;
        }
        // 校验CRC
        uint16_t recv_crc = (uint16_t)(raw[8 + data_len] | (raw[9 + data_len] << 8));
        uint16_t calc_crc = calculate_crc16(&raw[1], 1 + 2 + 2 + 2 + data_len);
        if (recv_crc != calc_crc) {
            send_response_frame(RESP_TYPE_ERROR, packet_index, ERR_CRC_MISMATCH);
            return ESP_ERR_INVALID_CRC;
        }

        const uint8_t *payload = &raw[8];
        if (cmd_type == CMD_TYPE_TIME_SYNC) {
            esp_err_t r = apply_time_sync_payload(payload, data_len);
            if (r == ESP_OK) {
                send_response_frame(RESP_TYPE_ACK, packet_index, ERR_SUCCESS);
            } else {
                send_response_frame(RESP_TYPE_ERROR, packet_index, ERR_FRAME_FORMAT);
            }
            return r;
        } else {
            // 非时间同步命令，按大数据传输处理（例如配置、固件等）
            if (!g_assembly.is_active) {
                esp_err_t br = assembly_begin(&g_assembly, total_packets);
                if (br != ESP_OK) {
                    send_response_frame(RESP_TYPE_ERROR, packet_index, ERR_BUFFER_FULL);
                    return br;
                }
            }
            esp_err_t sr = assembly_store(&g_assembly, packet_index, payload, data_len);
            if (sr == ESP_OK) {
                send_response_frame(RESP_TYPE_ACK, packet_index, ERR_SUCCESS);
                if (g_assembly.is_complete) {
                    send_response_frame(RESP_TYPE_COMPLETE, packet_index, ERR_SUCCESS);
                }
            } else {
                send_response_frame(RESP_TYPE_ERROR, packet_index, ERR_BUFFER_FULL);
            }
            return sr;
        }
    } else if (header == FRAME_HEADER_RESP) {
        // APP端响应帧（通常由设备主动发送，设备不需要解析），忽略
        return ESP_OK;
    }
    return ESP_ERR_INVALID_RESPONSE;
}

// ------------------ 公共接口实现 ------------------
bool ble_module_has_complete_data(void) {
    return g_assembly.is_complete;
}

size_t ble_module_get_complete_data(uint8_t *buffer, size_t buffer_len) {
    if (!g_assembly.is_complete || !g_assembly.buffer) return 0;
    if (!buffer || buffer_len < g_assembly.total_size) return 0;
    memcpy(buffer, g_assembly.buffer, g_assembly.total_size);
    size_t n = g_assembly.total_size;
    assembly_reset(&g_assembly);
    return n;
}

esp_err_t ble_register_time_sync_callback(void (*cb)(uint64_t utc_ms, int16_t tz_offset_min, uint8_t flags)) {
    time_sync_cb = cb;
    return ESP_OK;
}